package com.atguigu.lease.web.admin.controller.apartment;


import com.atguigu.lease.common.result.Result;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.model.enums.ReleaseStatus;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.fee.FeeValueVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;


@Tag(name = "公寓信息管理")
@RestController
@RequestMapping("/admin/apartment")
public class ApartmentController {

    @Autowired
    private ApartmentInfoService apartmentInfoService;

    @Autowired
    private ApartmentFacilityService apartmentFacilityService;

    @Autowired
    private ApartmentLabelService apartmentLabelService;

    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;

    @Autowired
    private GraphInfoService graphInfoService;


    @Operation(summary = "保存或更新公寓信息")
    @PostMapping("saveOrUpdate")
    public Result saveOrUpdate(@RequestBody ApartmentSubmitVo apartmentSubmitVo) {
        // 写之前认真看看 ApartmentSubmitVo 里面的内容，包括了页面所有

        //如果id不为null，说明要进行修改操作。那么修改之前需要将之前的旧关系全部删除

        if (apartmentSubmitVo.getId() != null) {

            Long apartmentId = apartmentSubmitVo.getId();

            // 删除旧的配套信息
            apartmentFacilityService.remove(new LambdaQueryWrapper<ApartmentFacility>().eq(ApartmentFacility::getApartmentId, apartmentId));

            // 删除旧的的标签
            apartmentLabelService.remove(new LambdaQueryWrapper<ApartmentLabel>().eq(ApartmentLabel::getApartmentId, apartmentId));

            // 删除旧的杂费值
            apartmentFeeValueService.remove(new LambdaQueryWrapper<ApartmentFeeValue>().eq(ApartmentFeeValue::getApartmentId, apartmentId));

            // 删除旧的图片信息，需要注意的是，不能只看 Id 还要匹配 所属的对象类型

            graphInfoService.remove(new LambdaQueryWrapper<GraphInfo>().eq(GraphInfo::getItemId, apartmentId).eq(GraphInfo::getItemType, ItemType.APARTMENT));

        }

        // 1. 保存公寓本身的基本信息
        apartmentInfoService.saveOrUpdate(apartmentSubmitVo);

        // 2. 保存关系表数据 包括 配套，标签，杂费值
        // 2-1 配套  ApartmentFacility(包括公寓id,设施id),不止一个配套，就不用 saveOrUpdate(ApartmentFacility);
        // saveOrUpdateBatch(entityList) 批量保存更新，那么就要创建一个 ApartmentFacility 集 合
        // 对所有配套的 id 进行流式操作，再和 公寓id 一起进行组装

        // List<ApartmentFacility> apartmentFacilityList = apartmentSubmitVo.getFacilityInfoIds().stream().map(fid -> ApartmentFacility.builder().apartmentId(apartmentSubmitVo.getId()).facilityId(fid).build()).collect(Collectors.toList());
        // apartmentFacilityService.saveOrUpdateBatch(apartmentFacilityList);

        apartmentFacilityService.saveOrUpdateBatch(apartmentSubmitVo.getFacilityInfoIds()
                .stream()
                .map(ApartmentFacility.builder().apartmentId(apartmentSubmitVo.getId())::facilityId)
                .map(ApartmentFacility.ApartmentFacilityBuilder::build)
                .collect(Collectors.toList()));

        // 2-2 标签  ApartmentLabel (包括公寓 id 和 房间 id )
        apartmentLabelService.saveOrUpdateBatch(apartmentSubmitVo.getLabelIds()
                .stream()
                .map(labelId -> new ApartmentLabel(apartmentSubmitVo.getId(), labelId))
                .collect(Collectors.toList()));

        // 2-3 杂费 ApartmentFeeValue(包括公寓 id 和 收费项value_id)
        apartmentFeeValueService.saveOrUpdateBatch(apartmentSubmitVo.getFeeValueIds()
                .stream()
                .map(apartmentId -> new ApartmentFeeValue(apartmentSubmitVo.getId(), apartmentId))
                .collect(Collectors.toList()));

        // 2-4 保存公寓图片信息

        graphInfoService.saveOrUpdateBatch(apartmentSubmitVo.getGraphVoList().stream().map(graphVo -> {
            GraphInfo graphInfo = new GraphInfo();
            graphInfo.setUrl(graphVo.getUrl());
            graphInfo.setName(graphVo.getName());
            graphInfo.setItemType(ItemType.APARTMENT);
            graphInfo.setItemId(apartmentSubmitVo.getId());
            return graphInfo;
        }).collect(Collectors.toList()));


        return Result.ok();
    }

    @Operation(summary = "根据条件分页查询公寓列表")
    @GetMapping("pageItem")

    // IPage<ApartmentItemVo> 对 ApartmentItemVo 进行分页操作 current 当前页  size 一页的条数  ApartmentQueryVo 传入的公寓查询实体
    // 包括了 省、市、区
    public Result<IPage<ApartmentItemVo>> pageItem(@RequestParam long current, @RequestParam long size, ApartmentQueryVo queryVo) {

        // 这里返回的是 ApartmentItemVo 不是 ApartmentInfo ,这里要看显示页面里面我们所需要的数据，数据不仅仅来源于公寓表
        // 这里我们需要准备一个 page  : Page.of(current ,size)

        IPage<ApartmentItemVo> apartmentItemVoPage = apartmentInfoService.pageItem(Page.of(current, size), queryVo);

        return Result.ok(apartmentItemVoPage);
    }

    @Operation(summary = "根据ID获取公寓详细信息")
    @GetMapping("getDetailById")
    public Result<ApartmentDetailVo> getDetailById(@RequestParam Long id) {
        // 思路，1.先获取 ApartmentInfo 信息，再获取剩下的 配套，标签，杂费，图片
        //      2.得到 ApartmentDetailVo，先将 ApartmentInfo 赋值，再挨个属性赋值

        // 1. 查询公寓基本信息

        ApartmentInfo apartmentInfo = apartmentInfoService.getById(id);

        // 2.查询配套信息 三个表 公寓表 公寓-配套关系表 配套表  要得到的是配套表集合，表联接查询（这个要作为一个模版）

        List<FacilityInfo> facilityInfoList = apartmentFacilityService.getFacilityInfoByApartmentId(id);

        // 3.查询标签信息

        List<LabelInfo> labelInfoList = apartmentLabelService.getLabelInfoByApartmentId(id);

        // 4.查询杂费信息，略有不同，这次是四张表

        List<FeeValueVo> feeValueVoList = apartmentFeeValueService.getFeeValueVoList(id);

        // 5.查询公寓关联图片信息，这里要注意区分公寓和房间的图片,然后  ApartmentDetailVo 需要的是 GraphVo ，比对一下 GraphInfo 和 GraphVo

        List<GraphInfo> graphInfoList = graphInfoService.list(new LambdaQueryWrapper<GraphInfo>().eq(GraphInfo::getItemType, ItemType.APARTMENT).eq(GraphInfo::getItemId, id));

        List<GraphVo> graphVoList = graphInfoList.stream().map(graphInfo -> {
            GraphVo graphVo = new GraphVo();
            // 多赋值少时，会自动忽略多余的属性

            BeanUtils.copyProperties(graphInfo, graphVo);

            return graphVo;

        }).collect(Collectors.toList());


        // 最终组装
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        BeanUtils.copyProperties(apartmentInfo,apartmentDetailVo);
        apartmentDetailVo.setFeeValueVoList(feeValueVoList);
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        apartmentDetailVo.setGraphVoList(graphVoList);
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        return Result.ok(apartmentDetailVo);


    }

    @Operation(summary = "根据id删除公寓信息")
    @DeleteMapping("removeById")
    public Result removeById(@RequestParam Long id) {

        // 删除公寓基本信息

        apartmentInfoService.removeById(id);

        // 删除公寓关联信息
        // 1. 配套
        apartmentFacilityService.remove(new LambdaQueryWrapper<ApartmentFacility>().eq(ApartmentFacility::getApartmentId,id));

        // 2. 标签

        apartmentLabelService.remove(new LambdaQueryWrapper<ApartmentLabel>().eq(ApartmentLabel::getApartmentId,id));


        // 3. 杂费值

        apartmentFeeValueService.remove(new LambdaQueryWrapper<ApartmentFeeValue>().eq(ApartmentFeeValue::getApartmentId,id));


        // 4.  图片

        graphInfoService.remove(new LambdaQueryWrapper<GraphInfo>().eq(GraphInfo::getItemType,ItemType.APARTMENT).eq(GraphInfo::getItemId,id));



        return Result.ok();
    }

    @Operation(summary = "根据id修改公寓发布状态")
    @PostMapping("updateReleaseStatusById")
    public Result updateReleaseStatusById(@RequestParam Long id, @RequestParam ReleaseStatus status) {

        apartmentInfoService.update(new LambdaUpdateWrapper<ApartmentInfo>().set(ApartmentInfo::getIsRelease,status).eq(ApartmentInfo::getId,id));

        return Result.ok();
    }

    @Operation(summary = "根据区县id查询公寓信息列表")
    @GetMapping("listInfoByDistrictId")
    public Result<List<ApartmentInfo>> listInfoByDistrictId(@RequestParam Long id) {

        List<ApartmentInfo> apartmentInfoList = apartmentInfoService.list(new LambdaQueryWrapper<ApartmentInfo>().eq(ApartmentInfo::getDistrictId, id));


        return Result.ok(apartmentInfoList);
    }
}














